package com.hh.flow.controller;

import com.hh.common.core.domain.R;
import com.hh.common.core.page.TableDataInfo;
import com.hh.common.utils.ExceptionUtil;
import com.hh.common.utils.MessageUtils;
import com.hh.flow.service.DefService;
import com.hh.log.annotaion.Log;
import com.hh.log.enums.BusinessType;
import com.hh.mybatisflex.controller.BaseController;
import com.monkey.flow.core.DefAppService;
import com.monkey.flow.core.SkipAppService;
import com.monkey.flow.core.domain.entity.FlowDefinition;
import com.monkey.flow.core.domain.entity.FlowNode;
import com.monkey.flow.core.domain.entity.FlowSkip;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 流程定义Controller
 *
 * @author hh
 * @date 2023-04-11
 */
@Validated
@RestController
@RequestMapping("/flow/definition")
public class DefController extends BaseController
{
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private DefAppService defAppService;

    @Resource
    private SkipAppService skipAppService;

    @Resource
    private DefService defService;

    /**
     * 分页查询流程定义列表
     */
    @GetMapping("/list")
    public TableDataInfo<FlowDefinition> list(FlowDefinition flowDefinition)
    {
        try {
            startPage();
            List<FlowDefinition> list = defAppService.getService().selectList(flowDefinition);
            return getDataTable(list);
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.page");
            logger.error(msg, e);
            return TableDataInfo.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }


    /**
     * 获取流程定义详细信息
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:query')")
    @GetMapping(value = "/{id}")
    public R<FlowDefinition> getInfo(@PathVariable("id") Long id)
    {
        try {
            return R.ok(defAppService.getService().selectById(id));
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.detail");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    /**
     * 获取流程定义详细信息
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:query')")
    @GetMapping(value = "/getNodeList/{definitionId}")
    public R<List<FlowNode>> getNodeList(@PathVariable("definitionId") Long definitionId)
    {
        return R.ok(defService.getNodeList(definitionId));
    }

    /**
     * 获取流程定义详细信息
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:query')")
    @GetMapping(value = "/getSkipList/{nodeId}")
    public R<List<FlowSkip>> getSkipList(@PathVariable("nodeId") Long nodeId)
    {
        FlowSkip skip = new FlowSkip();
        skip.setNodeId(nodeId);
        return R.ok(skipAppService.getService().selectList(skip));
    }

    /**
     * 新增流程定义
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:add')")
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @PostMapping
    public R add(@RequestBody FlowDefinition flowDefinition)
    {
        try {
            return R.ok(defAppService.getService().save(flowDefinition));
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.add");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    /**
     * 发布流程定义
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:publish')")
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @GetMapping("/publish/{id}")
    public R publish(@PathVariable("id") Long id)
    {
        return R.ok(defAppService.getService().publish(id));
    }

    /**
     * 取消发布流程定义
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:publish')")
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @GetMapping("/unPublish/{id}")
    public R unPublish(@PathVariable("id") Long id)
    {
        return R.ok(defAppService.getService().unPublish(id));
    }

    /**
     * 保存流程结点
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:saveNode')")
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @PostMapping("/saveNode")
    public R saveNode(@RequestBody List<FlowNode> nodeList, Long definitionId)
    {
        try {
            defService.saveNode(nodeList, definitionId);
            return R.ok();
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.save");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    /**
     * 保存流程跳转
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:saveNode')")
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @PostMapping("/saveSkip")
    public R saveSkip(@RequestBody List<FlowSkip> skipList, Long nodeId)
    {
        try {
            defService.saveSkip(skipList, nodeId);
            return R.ok();
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.save");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    /**
     * 修改流程定义
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:edit')")
    @Log(title = "流程定义", businessType = BusinessType.UPDATE)
    @PutMapping
    public R edit(@RequestBody FlowDefinition flowDefinition)
    {
        try {
            return R.ok(defAppService.getService().edit(flowDefinition));
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.update");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    /**
     * 删除流程定义
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:remove')")
    @Log(title = "流程定义", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public R remove(@PathVariable List<Long> ids)
    {
        try {
            return R.ok(defAppService.getService().remove(ids));
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.delete");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    @Log(title = "流程定义", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('flow:definition:importDefinition')")
    @PostMapping("/importDefinition")
    public R importDefinition(MultipartFile file) throws Exception {
        defAppService.importXml(file.getInputStream());
        return R.ok();
    }

    @Log(title = "流程定义", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('flow:definition:exportDefinition')")
    @PostMapping("/exportDefinition/{id}")
    public void exportDefinition(@PathVariable("id") Long id, HttpServletResponse response) throws Exception {
        Document document = defAppService.exportXml(id);
        // 设置生成xml的格式
        OutputFormat of = OutputFormat.createPrettyPrint();
        // 设置编码格式
        of.setEncoding("UTF-8");
        of.setIndent(true);
        of.setIndent("    ");
        of.setNewlines(true);

        //创建一个xml文档编辑器
        XMLWriter writer = new XMLWriter(response.getOutputStream(), of);
        writer.setEscapeText(false);
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/x-msdownload");
        response.setHeader("Content-Disposition", "attachment;");
        writer.write(document);
        writer.close();
    }
}
